package cn.px.service.purchase.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import cn.px.common.bean.AbstractPageResultBean;
import cn.px.common.exception.BusinessException;
import cn.px.common.model.UserInfo;
import cn.px.common.util.IdGeneratorUtils;
import cn.px.common.util.SecurityUtils;
import cn.px.common.util.StringUtils;
import cn.px.dao.bean.MyPage;
import cn.px.dao.config.aggregation.MyAggregateCondition;
import cn.px.dao.dto.purchase.PurchaseDispatchOrderListDTO;
import cn.px.dao.entity.purchase.PurchaseDispatchOrder;
import cn.px.dao.entity.purchase.PurchaseDispatchOrderList;
import cn.px.dao.entity.purchase.PurchaseOrderDispatchOrder;
import cn.px.dao.enums.FormActionEnum;
import cn.px.dao.mapper.purchase.PurchaseDispatchOrderListMapper;
import cn.px.dao.mapper.purchase.PurchaseDispatchOrderMapper;
import cn.px.dao.mapper.purchase.PurchaseOrderDispatchOrderMapper;
import cn.px.dao.vo.query.purchase.PurchaseDispatchOrderListVO;
import cn.px.service.base.impl.BaseServiceImpl;
import cn.px.service.purchase.PurchaseDispatchOrderListService;
import cn.px.service.util.DataField;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.additional.aggregation.AggregateType;
import tk.mybatis.mapper.weekend.Weekend;
import tk.mybatis.mapper.weekend.WeekendCriteria;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description 采购发运单明细 service 实现类
 * @author 品讯科技
 * @date 2024-08
 * @Version Copyright (c) 2020,北京乾元坤和科技有限公司 All rights reserved.
 */
@AllArgsConstructor
@Service("purchaseDispatchOrderListService")
public class PurchaseDispatchOrderListServiceImpl extends BaseServiceImpl<PurchaseDispatchOrderListMapper, PurchaseDispatchOrderList, PurchaseDispatchOrderListDTO> implements PurchaseDispatchOrderListService {

    private final PurchaseDispatchOrderMapper dispatchOrderMapper;
    private final PurchaseOrderDispatchOrderMapper orderDispatchOrderMapper;

    @Override
    public int batchDelete(List<String> ids) {
        Weekend<PurchaseDispatchOrderList> weekend = new Weekend<>(PurchaseDispatchOrderList.class);
        WeekendCriteria<PurchaseDispatchOrderList, Object> weekendCriteria = weekend.weekendCriteria();
        weekendCriteria.andIn(PurchaseDispatchOrderList::getId, ids);
        mapper.deleteByExample(weekend);
        return 1;
    }

    @Override
    public AbstractPageResultBean<PurchaseDispatchOrderListVO> selectPageList(PurchaseDispatchOrderListDTO record, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        return new MyPage(mapper.selectList(record));
    }

    @Override
    public AbstractPageResultBean<PurchaseDispatchOrderList> selectPageInfo(PurchaseDispatchOrderListDTO record, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        return new MyPage(mapper.selectList(record));
    }

    @Override
    public PurchaseDispatchOrderList saveModelByDTO(PurchaseDispatchOrderListDTO model) {
        // 校验是否已经存在
        Boolean storeOrigin = model.getStoreOrigin();
        if (storeOrigin != null && storeOrigin) {
            Weekend<PurchaseDispatchOrderList> weekend = new Weekend<>(PurchaseDispatchOrderList.class);
            WeekendCriteria<PurchaseDispatchOrderList, Object> weekendCriteria = weekend.weekendCriteria();
            weekendCriteria.andEqualTo(PurchaseDispatchOrderList::getDispatchOrderId, model.getDispatchOrderId());
            weekendCriteria.andEqualTo(PurchaseDispatchOrderList::getStoreOrigin, true);
            weekendCriteria.andEqualTo(PurchaseDispatchOrderList::getGoodsId, model.getGoodsId());
            int count = mapper.selectCountByExample(weekend);
            if (count > 0) {
                throw new BusinessException("从库里面添加的该货品，该发运单已经有了，不能再添加重复的");
            }
        }
        PurchaseDispatchOrderList result = super.saveModelByDTO(model);
        updateDispatchOrder(model.getDispatchOrderId());
        return result;
    }

    /**
     * 类型转换
     *
     * @param obj
     * @return
     */
    private PurchaseDispatchOrderListDTO convert(Object obj) {
        return JSON.parseObject(JSON.toJSONString(obj), PurchaseDispatchOrderListDTO.class);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateArrivedQuantity(List<PurchaseDispatchOrderList> list) {
        // 更新已到
        list.forEach(item -> {
            PurchaseDispatchOrderList elem = new PurchaseDispatchOrderList();
            elem.setId(item.getId());
            elem.setArrivedQuantity(item.getArrivedQuantity());
            mapper.updateByPrimaryKeySelective(elem);
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importList(String dispatchOrderId, List<PurchaseDispatchOrderList> items) {
        Weekend<PurchaseDispatchOrderList> weekend = new Weekend<>(PurchaseDispatchOrderList.class);
        WeekendCriteria<PurchaseDispatchOrderList, Object> weekendCriteria = weekend.weekendCriteria();
        weekendCriteria.andEqualTo(PurchaseDispatchOrderList::getDispatchOrderId, dispatchOrderId);
        List<PurchaseDispatchOrderList> orderLists = mapper.selectByExample(weekend);
        LocalDateTime now = LocalDateTime.now();
        UserInfo user = SecurityUtils.getUserInfo();
        if (CollectionUtil.isNotEmpty(orderLists)) {
            Map<String, String> map = new HashMap<>(orderLists.size());
            orderLists.forEach(item -> map.put(item.getNo(), item.getId()));
            if (CollectionUtil.isNotEmpty(items)) {
                items.forEach(item -> {
                    String id = map.get(item.getNo());
                    if (StringUtils.isNotEmpty(id)) {
                        PurchaseDispatchOrderList update = new PurchaseDispatchOrderList();
                        update.setId(id);
                        update.setDimension(item.getDimension());
                        update.setWeight(item.getWeight());
                        update.setVolume(item.getVolume());
                        update.setTaxMoney(item.getTaxMoney());
                        update.setUpdateTime(now);
                        update.setUpdateUserId(user.getUserId());
                        update.setUpdateUserName(user.getRealName());
                        update.setRemark(item.getRemark());
                        mapper.updateByPrimaryKeySelective(update);
                    }
                });
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handleListByPurchaseOrderDispatchOrder(PurchaseOrderDispatchOrder order, List<Object> objects, Integer action) {
        if (CollectionUtils.isEmpty(objects)) {
            return;
        }
        if (FormActionEnum.DELETE.getValue().equals(action)) {
            List<String> ids = objects.stream().map(item -> {
                PurchaseDispatchOrderListDTO listDTO = convert(item);
                return listDTO.getId();
            }).collect(Collectors.toList());
            batchDelete(ids);
        }
        if (FormActionEnum.ADD.getValue().equals(action)) {
            for (int i = objects.size() - 1; i >= 0; i--) {
                PurchaseDispatchOrderListDTO listDTO = convert(objects.get(i));
                otherAttr(order, listDTO);
                listDTO.setId(IdGeneratorUtils.getObjectId());
                super.saveModelHaveCreateInfo(listDTO);
            }
            return;
        }
        if (FormActionEnum.UPDATE.getValue().equals(action)) {
            for (int i = objects.size() - 1; i >= 0; i--) {
                PurchaseDispatchOrderListDTO listDTO = convert(objects.get(i));
                otherAttr(order, listDTO);
                super.modModelByDTO(listDTO);
            }
            return;
        }

    }

    /**
     * 添加其他属性
     *
     * @param model
     */
    private void otherAttr(PurchaseOrderDispatchOrder order, PurchaseDispatchOrderListDTO model) {
        model.setDispatchOrderId(order.getDispatchOrderId());
        model.setStoreOrigin(false);
    }

    @Override
    public void handleListByDispatchOrder(String orderId, List<PurchaseDispatchOrderListDTO> records) {
        if (CollectionUtil.isEmpty(records)) {
            return;
        }
        List<String> check = new ArrayList<>();
        for (PurchaseDispatchOrderListDTO item : records) {
            String checkStr = item.getPurchaseOrderId() + "_" + item.getGoodsId();
            if (check.contains(checkStr)) {
                continue;
            }
            check.add(checkStr);
            item.setDispatchOrderId(orderId);
            String id = item.getId();
            boolean flag = StringUtils.isEmpty(id);
            if (flag) {
                this.saveModelByDTO(item);
                continue;
            }
            this.modModelByDTO(item);
        }

        updateDispatchOrder(orderId);
        updateOrderDispatchOrder(orderId);
    }

    /**
     * 更新发运单 数据
     *
     * @param id
     */
    private void updateDispatchOrder(String id) {
        PurchaseDispatchOrder plan = new PurchaseDispatchOrder();
        // 统计金额
        MyAggregateCondition condition = MyAggregateCondition.builder();
        Weekend<PurchaseDispatchOrderList> weekend = new Weekend<>(PurchaseDispatchOrderList.class);
        WeekendCriteria<PurchaseDispatchOrderList, Object> weekendCriteria = weekend.weekendCriteria();
        weekendCriteria.andEqualTo(PurchaseDispatchOrderList::getDispatchOrderId, id);
        weekendCriteria.andEqualTo(PurchaseDispatchOrderList::getDelFlag, 0);
        condition.addAggregateProperty(DataField.fnToFieldName(PurchaseDispatchOrderList::getQuantity), AggregateType.SUM);
        List<PurchaseDispatchOrderList> sumList = mapper.selectAggregationByExample(weekend, condition);
        if (CollectionUtil.isEmpty(sumList) || sumList.get(0) == null) {
            plan.setQuantity(BigDecimal.ZERO);
        } else {
            PurchaseDispatchOrderList sumData = sumList.get(0);
            plan.setQuantity(sumData.getQuantity());
        }
        plan.setId(id);
        dispatchOrderMapper.updateByPrimaryKeySelective(plan);
    }

    /**
     * 更新关联
     *
     * @param id
     */
    private void updateOrderDispatchOrder(String id) {

        Weekend<PurchaseOrderDispatchOrder> weekend = new Weekend<>(PurchaseOrderDispatchOrder.class);
        WeekendCriteria<PurchaseOrderDispatchOrder, Object> weekendCriteria = weekend.weekendCriteria();
        weekendCriteria.andEqualTo(PurchaseOrderDispatchOrder::getDispatchOrderId, id);
        weekendCriteria.andEqualTo(PurchaseOrderDispatchOrder::getDelFlag, 0);
        List<PurchaseOrderDispatchOrder> orderList = orderDispatchOrderMapper.selectByExample(weekend);

        if (!CollectionUtils.isEmpty(orderList)) {
            orderList.forEach(item -> {
                PurchaseOrderDispatchOrder plan = new PurchaseOrderDispatchOrder();
                // 统计金额
                MyAggregateCondition condition = MyAggregateCondition.builder();
                Weekend<PurchaseDispatchOrderList> w = new Weekend<>(PurchaseDispatchOrderList.class);
                WeekendCriteria<PurchaseDispatchOrderList, Object> c = w.weekendCriteria();
                c.andEqualTo(PurchaseDispatchOrderList::getDispatchOrderId, id);
                c.andEqualTo(PurchaseDispatchOrderList::getPurchaseOrderId, item.getPurchaseOrderId());
                c.andEqualTo(PurchaseDispatchOrderList::getDelFlag, 0);
                condition.addAggregateProperty(DataField.fnToFieldName(PurchaseDispatchOrderList::getQuantity), AggregateType.SUM);
                List<PurchaseDispatchOrderList> sumList = mapper.selectAggregationByExample(w, condition);
                if (!CollectionUtil.isEmpty(sumList) && sumList.get(0) != null) {
                    PurchaseDispatchOrderList sumData = sumList.get(0);
                    plan.setQuantity(sumData.getQuantity());
                    plan.setId(item.getId());
                    orderDispatchOrderMapper.updateByPrimaryKeySelective(plan);
                }
            });
        }


    }


}
